package com.googlecode.bipol.war.services;

import java.io.Serializable;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import com.googlecode.bip.dao.DAOFactory;
import com.googlecode.bip.dao.QuestionDAO;
import com.googlecode.bip.dao.TopicDAO;
import com.googlecode.bip.dao.UserValueDAO;
import com.googlecode.bip.entity.IGenericUser;
import com.googlecode.bip.entity.IQuestion;
import com.googlecode.bip.entity.IQuestionValue;
import com.googlecode.bip.entity.ISurveyEntry;
import com.googlecode.bip.entity.ISurveyMetaData;
import com.googlecode.bip.entity.ITopic;
import com.googlecode.bip.entity.IUserValue;
import com.googlecode.bip.entity.impl.Question;
import com.googlecode.bip.entity.impl.QuestionValue;
import com.googlecode.bip.entity.impl.SurveyMetaData;
import com.googlecode.bip.entity.impl.Topic;
import com.googlecode.bipol.war.session.IBipSession;

/**
 * Default implementation of {@link SurveyManager}
 */
public class SurveyManagerImpl implements SurveyManager, Serializable {
    private final static long serialVersionUID = 1L;
    private final static Logger logger = Logger.getLogger(SurveyManagerImpl.class);
    private IBipSession bipSession;

    public SurveyManagerImpl(final IBipSession bipSession) {
        this.bipSession = bipSession;
    }

    @Override
    public List<ISurveyEntry> fetchSurvey(String idlocal)
            throws ServiceException
    {
        try {
            List<ISurveyEntry> survey = new ArrayList<ISurveyEntry>();

            final TopicDAO      topicDAO        = DAOFactory.getDAOFactory().getTopicDAO();
            final QuestionDAO   questionDAO     = DAOFactory.getDAOFactory().getQuestionDAO();
            final UserValueDAO  userValueDAO    = DAOFactory.getDAOFactory().getUserValueDAO();

            if( bipSession.getGenericUser() == null ) {
                logger.fatal( "iUser is null ! (new user)" );
                 }

            final Timestamp userdate = bipSession.getUserDate();
            final int       userId   = bipSession.getGenericUser().getIdUser();

            // Add the metadata to survey
            ISurveyMetaData metaData = new SurveyMetaData(userdate);
            survey.add(metaData);

            int numberOfQuestions = 0;
            int numberOfAnswers = 0;

            List<ITopic> topics = topicDAO.getAllTopics();

            for (ITopic t : topics) {
                if (idlocal.equals(t.getIdLocal())) {
                    if (t.getIdTopic() >= 0) {
                        survey.add(t);

                        List<IQuestion> questions = questionDAO.findQuestions( t, t.getIdLocal() );

                        for (IQuestion q : questions) {
                            // Is there an existing UserValue ?
                            IUserValue userValue = userValueDAO.getUserValue(
                                    userId,
                                    q.getIdQuestion(),
                                    userdate);

                            if (userValue.getUserValue() != null) {
                                numberOfAnswers++;
                                }

                            QuestionValue questionValue = new QuestionValue( q, userValue );
                            survey.add( questionValue );
                            numberOfQuestions++;
                        }
                    }
                }
            }
            if( logger.isDebugEnabled() ) {
                logger.debug( "numberOfAnswers = " + numberOfAnswers );
                }

            metaData.setNumberOfAnswers(numberOfAnswers);
            metaData.setNumberOfQuestions(numberOfQuestions);

            return survey;
            }
        catch (Exception e) {
            logger.fatal("fetchSurvey error", e);
            throw new ServiceException("Error when getting survey: "
                    + e.getMessage(), e);
            }
    }

    @Override
    public List<ISurveyEntry> postSurvey( final List<ISurveyEntry> survey )
        throws ServiceException
    {
        try {
            final IGenericUser  iUser   = bipSession.getGenericUser();
            final UserValueDAO  dao     = DAOFactory.getDAOFactory()
                    .getUserValueDAO();

            ISurveyMetaData metaData = null;

            // Get back meta data
            for (ISurveyEntry entry : survey) {
                if (entry.isISurveyMetaData()) {
                    metaData = ISurveyMetaData.class.cast(entry);
                    break;
                }
            }

            // Save UserValues
            int numberOfQuestions = 0;
            int numberOfAnswers = 0;
            for (ISurveyEntry entry : survey) {
                logger.info( "entry:" + entry );
                if (entry.isIQuestion()) {
                    //IQuestion q = IQuestion.class.cast(entry);
                    IQuestionValue q = IQuestionValue.class.cast( entry );
                    q.setIdUser(iUser.getIdUser()); // Make sure the remote user is answering it's own survey
                    //if (q.getUserComment() == null) {q.setUserComment("");} // FIXME: Avoid SQL error
                    if (q.getUserValue() != null) {
//                        IUserValue userValue = new UserValue();
//                        userValue.setIdQuestion(q.getIdQuestion());
//                        userValue.setIdUser(iUser.getIdUser());
//                        userValue.setUserValue(q.getUserValue());
//                        userValue.setUserComment(""); // Not Yet Implemented
//                                                        // (user can add a
//                                                        // comment to each
//                                                        // answer)
//                        userValue.setUserDate(metaData.getUserDate());
//
//                        dao.updateUserValue(userValue);

                        dao.updateUserValue( q );
                        numberOfAnswers++;
                    }
                    numberOfQuestions++;
                }

                // else ITopic
            }
            metaData.setNumberOfAnswers(numberOfAnswers);
            metaData.setNumberOfQuestions(numberOfQuestions);
        } catch (Exception e) {
            logger.fatal("postSurvey error", e);
            throw new ServiceException("Error when saving survey: "
                    + e.getMessage(), e);
        }

        return survey;
    }

    @Override
    public Map<String,Object> getSurveyTree() throws ServiceException {
        Map<String,Object> survey = new HashMap<String,Object>();
        // Survey: {name:"survey", items: [{name:"topic #$id", topic:$topicInstance, items:[...]}, ...]}
        List<Map<String,Object>> topicsList = new ArrayList<Map<String,Object>>();
        survey.put("name", "survey");
        survey.put("items", topicsList);
        // Also add an 'empty' topic model for new topic creation
        ITopic topicModel = new Topic();
        topicModel.setParentIdTopic(0);
        survey.put("topicModel", topicModel);
        try {
            List<ITopic> topics = DAOFactory.getDAOFactory().getTopicDAO().getAllTopics();
            for (ITopic t : topics) {
                if (t.getIdTopic() >= 0 && t.getName() != null) {
                    // {name:"topic #$id", topic: $topicInstance, items:[...]}
                    Map<String,Object> topic = new HashMap<String,Object>();
                    topic.put("name","topic #"+t.getIdTopic());
                    topic.put("topic", t);
                    List<Map<String,Object>> questionsList = new ArrayList<Map<String,Object>>();
                    topic.put("items", questionsList);
                    topicsList.add(topic);
                    // Also add an 'empty' question model for new question creation
                    IQuestion questionModel = new Question();
                    questionModel.setParentIdTopic(t.getIdTopic());
                    questionModel.setIdLocal(t.getIdLocal());
                    topic.put("questionModel", questionModel);
                    List<IQuestion> questions = DAOFactory.getDAOFactory()
                            .getQuestionDAO()
                            .findQuestions(t.getIdTopic(), t.getIdLocal());
                    for (IQuestion q : questions) {
                        // {name:"question #$id", question:$questionInstance}
                        Map<String,Object> question = new HashMap<String,Object>();
                        question.put("name","question #"+q.getIdQuestion());
                        question.put("question", q);
                        questionsList.add(question);
                    }
                }
            }
        }
        catch (Exception e) {
            logger.fatal("getSurveyTree error", e);
            throw new ServiceException("Error when getting survey: "
                    + e.getMessage(), e);
        }
        return survey;
    }


}
